#include <iostream>
#include <cstdio>
#include <vector>
#include <queue>
#include <cmath>
#include <algorithm>

#define FOR(i,a,n) for(int i=a,_n(n);i<_n;++i)
#define REP(i,n) FOR(i,0,n)

const double INF = 1000000000;

using namespace std;

class Graph
{
    struct Edge
    {
        int vs,vt;
        double w;
        Edge *next;
        void Set(int a,int b,double c,Edge* nt)
        {
            vs = a, vt = b, w = c, next = nt;
        }
    };
    vector<Edge> edge;
    vector<Edge*> head;
    int vn,arcn;
public:
    Graph(int n,int m)
    {
        vn = n + 1;
        arcn = 0;
        edge.reserve(m+10);
        head.resize(vn*2,(Edge*)NULL);
    }
    void AddArc(int vs,int vt,double w)
    {
      //  printf("Add %d->%d (%f)",vs,vt,w);
        //cout<<endl;
        edge[arcn].Set(vs,vt,w,head[vs]);
        head[vs] = &edge[arcn++];
    }
    bool HasAns(int root)
    {
        queue<int> q;
        vector<bool> done(vn,false);
        done[root] = true;
        q.push(root);
        int cnt = 0;
        while(!q.empty())
        {
            int vs = q.front();q.pop();
                        //printf("vs = %d\n",vs);
            cnt++;
            for(Edge *ep=head[vs];ep;ep=ep->next) if(!done[ep->vt])
            {
                done[ep->vt] = true;
                q.push(ep->vt);
            }
        }
      //  cout<<cnt<<endl;
        return cnt == vn-1;
    }
    void GetAns(int root)
    {
        if(!HasAns(root))
        {
            puts("poor snoopy");
            return;
        }
        double ans = 0;
        int cnt = 0;
        while(true)
        {
           // printf("cnt=%d ans = %f\n",cnt++,ans);
           // getchar();
            vector<double> in(vn,INF);
            vector<int> pre(vn,-1);
            in[root] = 0;
            for(Edge *ep=&edge[0];ep!=&edge[arcn];++ep) if(ep->w<in[ep->vt])
            {
                in[ep->vt] = ep->w;
                pre[ep->vt] = ep->vs;
            }
            REP(i,vn) if(in[i]!=INF)
            {
                ans += in[i];
            }
            vector<int> toGi(vn,-1);
            vector<int> done(vn,-1);
            bool canBreak = true;
            REP(i,vn) toGi[i] = i;
            REP(i,vn) if(pre[i]!=-1&&done[i]==-1)
            {
                for(int p=i;p!=-1;p=pre[p])
                {
                   // printf("pre[%d]=%d\n",p,pre[i]);
                    if(done[p]==i)
                    {
                        canBreak = false;
                        for(int q=pre[p];q!=p;q=pre[q])
                        {
                            toGi[q] = p;
                        }
                        break;
                    }
                    else if(done[p]!=-1) break;
                    done[p] = i;
                }
            }
            if(canBreak) break;
            for(Edge *ep=&edge[0];ep!=&edge[arcn];++ep)
            {
                int vt = ep->vt;
                ep->vs = toGi[ep->vs], ep->vt = toGi[ep->vt];
                if(ep->vs==ep->vt) ep->w = INF;
                else if(in[vt]!=INF) ep->w -= in[vt];
            }
        }
        printf("%.2f\n",ans);
    }
};

struct House
{
    double x,y;
    double Dist(House h)
    {
        return sqrt((x-h.x)*(x-h.x)+(y-h.y)*(y-h.y));
    }
};

House house[110];
int main()
{
    //freopen("E:/code/Desktop/Application_3/in.txt","r",stdin);
    int n,m;
    while(cin>>n>>m)
    {
        Graph g(n,m);
        FOR(i,1,n+1)
        {
            scanf("%lf%lf",&house[i].x,&house[i].y);
        }
        REP(i,m)
        {
            int vs,vt;
            double w;
            scanf("%d%d",&vs,&vt);
            w = house[vs].Dist(house[vt]);
            if(vs!=vt) g.AddArc(vs,vt,w);
        }
        g.GetAns(1);
    }
    return 0;
}
